package acme.bloodtime.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import dao.api.BaseDAO;
import dao.api.DataObject;

/**
 * 
 * @author Manuel A. Quintero V.
 * 
 */

public abstract class BloodTimeBaseDAO extends BaseDAO {
    @Override
    public String getTableName() {
        String tableName = super.getTableName();
        if (tableName.endsWith("DAO")) {
            return tableName.substring(0, tableName.length() - 3);
        }
        return tableName;
    }

    protected void dropTable() throws SQLException {
        StringBuffer strbuf = new StringBuffer();

        strbuf.append("DROP TABLE IF EXISTS ");
        strbuf.append(getTableName());
        strbuf.append(" CASCADE");

        System.err.println(strbuf.toString());

        connection.createStatement().execute(strbuf.toString());
    }

    protected void internalDelete(DataObject dataObject, Class<? extends DataObject> dataObjectClass)
            throws SQLException {
        checkCache(dataObject, CHECK_DELETE);
        checkClass(dataObject, dataObjectClass, CHECK_DELETE);

        StringBuffer strbuf = new StringBuffer();

        strbuf.append("DELETE FROM ");
        strbuf.append(getTableName());

        strbuf.append(" WHERE ");
        strbuf.append(DataObject.ID);
        strbuf.append(" = ");
        strbuf.append(dataObject.getId());

        System.err.println(strbuf.toString());

        connection.createStatement().execute(strbuf.toString());

        dtaSession.del(dataObject);
    }

    public DataObject loadById(int id) throws SQLException {
        StringBuffer strbuf = new StringBuffer();

        strbuf.append("SELECT * FROM ");
        strbuf.append(getTableName());

        strbuf.append(" WHERE ");
        strbuf.append(DataObject.ID);
        strbuf.append(" = ");
        strbuf.append(id);

        System.err.println(strbuf.toString());

        ResultSet rs = //
        connection.createStatement().executeQuery(strbuf.toString());

        if (rs.next()) {
            return resultSetToDO(rs);
        }

        return null;
    }

    protected abstract DataObject resultSetToDO(ResultSet rs) throws SQLException;

    public List<DataObject> listAll(int lim, int off) throws SQLException {
        StringBuffer strbuf = new StringBuffer();

        strbuf.append("SELECT * FROM ");
        strbuf.append(getTableName());

        if (lim >= 0 && off >= 0) {
            strbuf.append(" LIMIT  ");
            strbuf.append(lim);
            strbuf.append(" OFFSET ");
            strbuf.append(off);
        }

        System.err.println(strbuf.toString());

        ResultSet rs = //
        connection.createStatement().executeQuery(strbuf.toString());

        List<DataObject> ret = new ArrayList<DataObject>();

        while (rs.next()) {
            ret.add(resultSetToDO(rs));
        }

        return ret;
    }

    // --------------------------------------------------------------------------------

    @Override
    public List<DataObject> listAll() throws SQLException {
        return listAll(-1, -1);
    }

    // --------------------------------------------------------------------------------

    @Override
    public int countAll() throws SQLException {
        StringBuffer strbuf = new StringBuffer();

        strbuf.append("SELECT COUNT(*) FROM ");
        strbuf.append(getTableName());

        System.err.println(strbuf.toString());

        ResultSet rs = //
        connection.createStatement().executeQuery(strbuf.toString());

        rs.next();

        return rs.getInt("count");
    }

    protected int getNextId() throws SQLException {
        StringBuffer strbuf = new StringBuffer();

        strbuf.append("SELECT nextval(");
        strbuf.append(singleQuotes(getTableName() + "_id_seq"));
        strbuf.append(")");

        System.err.println(strbuf.toString());

        ResultSet rs = //
        connection.createStatement().executeQuery(strbuf.toString());

        if (!rs.next()) {
            throw new IllegalStateException("!rs.next()");
        }

        return rs.getInt("nextval");
    }
}
